package com.star.spring.ratelimit.util;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 用户代理解析工具类
 * 
 * @author star
 * @since 2025-01-24
 */
@Slf4j
public class UserAgentParser {

    @Data
    public static class UserAgentInfo {
        private String browser;
        private String operatingSystem;
        private String device;
    }

    // 浏览器正则表达式
    private static final Pattern[] BROWSER_PATTERNS = {
        Pattern.compile("Chrome/([0-9.]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Firefox/([0-9.]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Safari/([0-9.]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Edge/([0-9.]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Opera/([0-9.]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("MSIE ([0-9.]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Trident.*rv:([0-9.]+)", Pattern.CASE_INSENSITIVE)
    };

    // 操作系统正则表达式
    private static final Pattern[] OS_PATTERNS = {
        Pattern.compile("Windows NT ([0-9.]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Windows ([0-9.]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Mac OS X ([0-9._]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Linux", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Android ([0-9.]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("iPhone OS ([0-9._]+)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("iPad.*OS ([0-9._]+)", Pattern.CASE_INSENSITIVE)
    };

    // 设备正则表达式
    private static final Pattern[] DEVICE_PATTERNS = {
        Pattern.compile("iPhone", Pattern.CASE_INSENSITIVE),
        Pattern.compile("iPad", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Android", Pattern.CASE_INSENSITIVE),
        Pattern.compile("Windows Phone", Pattern.CASE_INSENSITIVE),
        Pattern.compile("BlackBerry", Pattern.CASE_INSENSITIVE)
    };

    /**
     * 解析用户代理字符串
     */
    public static UserAgentInfo parse(String userAgent) {
        if (userAgent == null || userAgent.trim().isEmpty()) {
            return createDefaultInfo();
        }

        UserAgentInfo info = new UserAgentInfo();
        
        // 解析浏览器
        info.setBrowser(parseBrowser(userAgent));
        
        // 解析操作系统
        info.setOperatingSystem(parseOperatingSystem(userAgent));
        
        // 解析设备
        info.setDevice(parseDevice(userAgent));
        
        return info;
    }

    /**
     * 解析浏览器信息
     */
    private static String parseBrowser(String userAgent) {
        for (Pattern pattern : BROWSER_PATTERNS) {
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                String browser = matcher.group(0);
                if (browser.toLowerCase().contains("chrome")) {
                    return "Chrome " + extractVersion(browser);
                } else if (browser.toLowerCase().contains("firefox")) {
                    return "Firefox " + extractVersion(browser);
                } else if (browser.toLowerCase().contains("safari")) {
                    return "Safari " + extractVersion(browser);
                } else if (browser.toLowerCase().contains("edge")) {
                    return "Edge " + extractVersion(browser);
                } else if (browser.toLowerCase().contains("opera")) {
                    return "Opera " + extractVersion(browser);
                } else if (browser.toLowerCase().contains("msie") || browser.toLowerCase().contains("trident")) {
                    return "Internet Explorer " + extractVersion(browser);
                }
            }
        }
        return "Unknown Browser";
    }

    /**
     * 解析操作系统信息
     */
    private static String parseOperatingSystem(String userAgent) {
        for (Pattern pattern : OS_PATTERNS) {
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                String os = matcher.group(0);
                if (os.toLowerCase().contains("windows")) {
                    return "Windows " + extractVersion(os);
                } else if (os.toLowerCase().contains("mac os x")) {
                    return "macOS " + extractVersion(os);
                } else if (os.toLowerCase().contains("linux")) {
                    return "Linux";
                } else if (os.toLowerCase().contains("android")) {
                    return "Android " + extractVersion(os);
                } else if (os.toLowerCase().contains("iphone os")) {
                    return "iOS " + extractVersion(os);
                } else if (os.toLowerCase().contains("ipad")) {
                    return "iPadOS " + extractVersion(os);
                }
            }
        }
        return "Unknown OS";
    }

    /**
     * 解析设备信息
     */
    private static String parseDevice(String userAgent) {
        for (Pattern pattern : DEVICE_PATTERNS) {
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                String device = matcher.group(0);
                if (device.toLowerCase().contains("iphone")) {
                    return "iPhone";
                } else if (device.toLowerCase().contains("ipad")) {
                    return "iPad";
                } else if (device.toLowerCase().contains("android")) {
                    return "Android Device";
                } else if (device.toLowerCase().contains("windows phone")) {
                    return "Windows Phone";
                } else if (device.toLowerCase().contains("blackberry")) {
                    return "BlackBerry";
                }
            }
        }
        return "Desktop";
    }

    /**
     * 提取版本号
     */
    private static String extractVersion(String text) {
        Pattern versionPattern = Pattern.compile("([0-9.]+)");
        Matcher matcher = versionPattern.matcher(text);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return "";
    }

    /**
     * 创建默认信息
     */
    private static UserAgentInfo createDefaultInfo() {
        UserAgentInfo info = new UserAgentInfo();
        info.setBrowser("Unknown Browser");
        info.setOperatingSystem("Unknown OS");
        info.setDevice("Unknown Device");
        return info;
    }
}
